package com.blue.Impl.author;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.blue.common.constant.CommonConstant;
import com.blue.common.exception.CustomException;
import com.blue.common.utils.AESUtils;
import com.blue.common.utils.ConvertUtils;
import com.blue.common.utils.JwtUtils;
import com.blue.common.utils.RedisUtils;
import com.blue.dto.author.UserDTO;
import com.blue.po.author.RolePO;
import com.blue.po.author.UserPO;
import com.blue.po.author.UserRolePO;
import com.blue.service.author.ILoginService;
import com.blue.service.author.IRoleService;
import com.blue.service.author.IUserService;
import com.blue.vo.author.RoleVO;
import com.blue.vo.author.UserVO;
import com.github.yulichang.query.MPJQueryWrapper;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.wf.captcha.ArithmeticCaptcha;
import com.wf.captcha.base.Captcha;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.nio.charset.StandardCharsets;
import java.util.*;

@Service
public class LoginServiceImpl implements ILoginService {
    @Resource
    private RedisUtils redisUtils;
    @Autowired
    private IUserService userService;
    @Autowired
    private IRoleService roleService;

    @Override
    public Map<String, Object> captchaImage() {
        String key = "captcha_key:" + UUID.randomUUID();
        //以下6行是新加的代码
        Captcha captcha = new ArithmeticCaptcha(115, 30);  //创建算术验证码
        String code = captcha.text(); //得到算术验证码的计算值
        redisUtils.cacheValue(key, code, 60);
        Map<String, Object> map = new HashMap<>();
        map.put("key", key);
        map.put("code", captcha.toBase64());
        return map;
    }

    @Override
    public UserVO login(UserDTO requestDTO, HttpServletRequest request) throws Exception {
        //校验密码验证码
        UserVO userVO = verify(requestDTO);
        //查询角色
        MPJLambdaWrapper<RolePO> queryWrapper = JoinWrappers.lambda(RolePO.class)
                .selectAll(RolePO.class)
                .leftJoin(UserRolePO.class, UserRolePO::getRoleId, RolePO::getRoleId)
                .eq(UserRolePO::getUserId, userVO.getUserId())
                .eq(RolePO::getStatus, CommonConstant.NORMAL);
        List<RolePO> rolePOS = roleService.list(queryWrapper);
        if (CollectionUtils.isEmpty(rolePOS)) {
            throw new CustomException("账号角色查询异常");
        }
        //如果角色数量为1直接返回token
        if (rolePOS.size() == 1) {
            //组装token参数
            Map<String, String> userMap = new HashMap<>();
            userMap.put("userId", userVO.getUserId());
            userMap.put("deptId", userVO.getDeptId());
            userMap.put("leaderId", userVO.getLeaderId());
            RoleVO roleVO = ConvertUtils.convert(RoleVO.class, rolePOS.get(0));
            userVO.setRole(roleVO);
            userMap.put("roleId", roleVO.getRoleId());
            String userJson = JSON.toJSONString(userMap);
            String token = JwtUtils.createJwt(userJson);
            //加密token
            token = AESUtils.encrypt(token);
            userVO.setToken(token);
        } else {
            List<RoleVO> roleVOS = ConvertUtils.convertList(RoleVO.class, rolePOS);
            userVO.setRoles(roleVOS);
        }
        return userVO;
    }

    @Override
    public UserVO getToken(UserDTO requestDTO, HttpServletRequest request) throws Exception {
        //校验密码验证码
        UserVO userVO = verify(requestDTO);
        //获取角色信息
        RolePO rolePO = roleService.getOne(new LambdaQueryWrapper<RolePO>()
                .select(RolePO::getRoleId, RolePO::getRoleName)
                .eq(RolePO::getRoleId, requestDTO.getRoleId())
                .eq(RolePO::getStatus, CommonConstant.NORMAL));
        RoleVO roleVO = ConvertUtils.convert(RoleVO.class, rolePO);
        userVO.setRole(roleVO);
        //组装token参数
        Map<String, String> userMap = new HashMap<>();
        userMap.put("userId", userVO.getUserId());
        userMap.put("deptId", userVO.getDeptId());
        userMap.put("leaderId", userVO.getLeaderId());
        userMap.put("roleId", roleVO.getRoleId());
        String userJson = JSON.toJSONString(userMap);
        String token = JwtUtils.createJwt(userJson);
        //加密token
        token = AESUtils.encrypt(token);
        userVO.setToken(token);
        return userVO;
    }

    /**
     * 校验数据
     *
     * @param requestDTO
     * @return
     * @throws Exception
     */
    private UserVO verify(UserDTO requestDTO) throws Exception {
        String key = requestDTO.getKey();
        if (StringUtils.isNotBlank(key)) {
            String value = (String) redisUtils.getValue(key);
            if (StringUtils.isBlank(value)) {
                throw new CustomException("验证码已过期！");
            }
            String captcha = requestDTO.getCaptcha();
            if (!value.equals(captcha)) {
                throw new CustomException("验证码错误！");
            }
        }
        String userNo = new String(Base64.getDecoder().decode(requestDTO.getUserNo()), StandardCharsets.UTF_8);
        String passWord = new String(Base64.getDecoder().decode(requestDTO.getPassword()), StandardCharsets.UTF_8);
        //加密用户密码并校验
        passWord = AESUtils.encrypt(passWord);
        UserPO userPO = userService.getOne(new LambdaQueryWrapper<UserPO>()
                .select(UserPO::getUserId, UserPO::getStatus, UserPO::getUsername, UserPO::getHeadPic, UserPO::getDeptId, UserPO::getLeaderId)
                .eq(UserPO::getUserNo, userNo)
                .eq(UserPO::getPassword, passWord));
        if (userPO == null) {
            throw new CustomException("账户密码错误!");
        }
        if (CommonConstant.DISABLE.equals(userPO.getStatus())) {
            throw new CustomException("账户已被禁用，请联系管理员！");
        }
        return ConvertUtils.convert(UserVO.class, userPO);
    }
}
